#pragma once

#include <list>
#include "GamePlayer.h"

#pragma region TYPEDEFS

// Any estimation or precise calculation of a player standing/score.
// Potentially also a delta (change) of same.
typedef int						ExpectedValue;

// A volatile identifier for a player.
// It indexes their position around a virtual table.
typedef unsigned short			SeatNumber;

// A collection of adjacent, potentially upcoming GameStates.
class GameState;
typedef std::list<GameState*>	StateList;

#pragma endregion

/*	A node that contains all statistics for one possible midpoint
	in a game.
	
	Every game is modeled as a decision tree
	where the paths-between-nodes represent the actions
	that players can 'take' (put into effect).
	There is no theoretical limit to a node's outward paths,
	and loops/cycles are permitted.

	Games are thought to consist of multiple 'sequences',
	or linked trees.  See getNextSequence() for more details.

	GameEngine uses GameState::INITIAL->getNextSequence()
	to start a new game of a child type, so please do not use
	this library to host multiple game types
	within the same executable.
*/
class GameState
{
public:
	/*	@return	the answer to the question "Whose turn is it?"
	*/
	virtual
	GamePlayer*		getActivePlayer() = 0;

	/*	Determine the next 'phase' of the game.
		Many, if not most, games do not consist of a single set of game mechanics.
		Instead, they are broken up into distinct periods, each with its own
		combination of stats and rules.
		An example of a single-sequence game is Snakes and Ladders:
		-	Every turn consists of rolling two dice, moving the player token,
			and resolving a landing event (snake, ladder, free space).
		An example of a multi-sequence game is Cribbage:
		-	Its first sequence consists of the deal, hand selection, and discards.
		-	Its second sequence consists of individual card plays and pegging.
		-	Its third sequence consists of scoring the hand.
		As such, each sequence should be a distinct class descendant of GameState,
		and when the Next Sequence is obtained, initialization of the upcoming
		sequences stats should occur.
		This method will be called by GameEngine whenever currentGameState.isLeaf().
		If NONE is returned, the game will end.
		@return	root node of the next phase of the game
	*/
	virtual
	GameState*		getNextSequence() = 0;

	// The following two methods were made virtual to permit more efficient solutions.
	// While it can be predicted that a list of outward actions takes some time to assemble,
	// there may be an 'end game' flag in some game implementations that can be returned instead.

	/*	The final nodes of a tree are known as leaves.
		They may appear at any level, but their distinguishing feature
		is that no states proceed from them.  They are dead ends.
		@return	true only if the list of outward leading paths is empty
	*/
	virtual
	bool			isLeaf()
					{
						return listAvailableActions().size() == 0;
					} // end method stub

	/*	All non-leaf nodes of a tree are known as branches.
		@return	true only if the list of outward leading paths is NOT empty
	*/
	virtual
	bool			isBranch()
					{
						return listAvailableActions().size() != 0;
					} // end method stub

	/*	GameStates lead to other GameStates as players take actions.
		The choices of actions that are available are identified
		by the GameStates they lead to.
		@return	StateList, an iterable collection of proceeding GameStates
	*/
	virtual
	StateList&		listAvailableActions() = 0;

	/*	Retrieve a value for this GameState from the perspective of the game itself.
		Depending on the game implemented, there may be many statistics kept per player,
		and each statistic may or may not contribute towards winning.
		Sometimes there is a traditional, single "score" that a player has,
		but other times, there is no clear indicator of who is in the lead.
		Regardless, for the purposes of evaluation, player standings
		must be estimated with a decimal value via this method.
		The value returned must be deterministic,
		and a higher value indicates a stronger standing in comparisons.
		@param	SeatNumber	index of the player being evaluated
		@return				estimated standing of indexed player
	*/
	virtual
	ExpectedValue	score(SeatNumber) = 0;

	/*	A signal that indicates that a player chose this state
		and the GameEngine accepted it as a valid transition.
	*/
	virtual
	void			transitionFrom(GameState*) {}

	/*	A signal that indicates that a player chose a state
		that this state leads to, once the GameEngine accepted it.
	*/
	virtual
	void			transitionTo(GameState*) {}

	// Used to indicate "game over" or other inactive engine states.
	static
	GameState*		
	const			NONE;
	
	// The one game state that sets up and initiates all new games of its type.
	static
	GameState*		
	const			INITIAL;

protected:
	// The score value held by every player at the genesis of the implemented game.
	// It is conceptually 0, but some games are modelled around the idea
	// of starting with a high standing, and proceeding until one or more players
	// have hit rock bottom.  In that case, a starting value may be 100.
	static
	ExpectedValue
	const			INITIAL_PLAYER_SCORE;

	/*	Only descendant classes of GameState may be 'played',
		so we prevent this class from being instantiated
		by outside influences.
	*/
					GameState() {	
					} // end constructor
}; // end class
